package cn.net.xyan.blossom.kotlin

import java.text.SimpleDateFormat
import java.util.*
import java.util.Calendar


fun Date.normalize(timeZone: TimeZone? = null): Date {
    val df = SimpleDateFormat("yyyyMMdd")
    if (timeZone != null) df.timeZone = timeZone

    val string = df.format(this)
    return df.parse(string)
}

object DateExt {
    val now: Date get() = Date()
    val today: Date get() = now.normalize()
    val yesterday: Date get() = today - DateDiff.Day
    val tomorrow: Date get() = today + DateDiff.Day
}

enum class DateDiffUnit {
    Second, Minute, Hour, Day, Month, Week, Year
}

data class DateDiff(val value: Int, val unit: DateDiffUnit) : Comparable<DateDiff> {

    companion object {
        val Second = DateDiff(1, DateDiffUnit.Second)
        val Minute = DateDiff(1, DateDiffUnit.Minute)
        val Hour = DateDiff(1, DateDiffUnit.Hour)
        val Day = DateDiff(1, DateDiffUnit.Day)
        val Month = DateDiff(1, DateDiffUnit.Month)
        val Week = DateDiff(1, DateDiffUnit.Week)
        val Year = DateDiff(1, DateDiffUnit.Year)
    }

    override fun compareTo(other: DateDiff): Int {
        if (unit != other.unit) {
            throw StatusAndMessageError("计量单位 $unit 与 ${other.unit}不同")
        }

        return value.compareTo(other.value)
    }

    operator fun plus(other: DateDiff): DateDiff {
        if (unit != other.unit) {
            throw StatusAndMessageError("计量单位 $unit 与 ${other.unit}不同")
        }

        return DateDiff(value + other.value, unit)
    }

    operator fun times(times: Int): DateDiff {
        return DateDiff(value * times, unit)
    }

    operator fun minus(other: DateDiff): DateDiff {
        return plus(other * (-1))
    }
}

operator fun Int.times(diff: DateDiff): DateDiff {
    return DateDiff(this * diff.value, diff.unit)
}

operator fun Date.plus(diff: DateDiff): Date {

    val cal = Calendar.getInstance()
    cal.time = this
    val type = when (diff.unit) {
        DateDiffUnit.Second -> Calendar.SECOND
        DateDiffUnit.Minute -> Calendar.MINUTE
        DateDiffUnit.Hour -> Calendar.HOUR
        DateDiffUnit.Day -> Calendar.DAY_OF_MONTH
        DateDiffUnit.Week -> Calendar.WEEK_OF_MONTH
        DateDiffUnit.Month -> Calendar.MONTH
        DateDiffUnit.Year -> Calendar.YEAR
    //else -> throw StatusAndMessageError("Unknown unit:${diff.unit}")
    }
    cal.add(type, diff.value)

    return cal.time

}

operator fun Date.minus(diff: DateDiff): Date {
    return this + (diff * -1)
}